"use strict";

var _sliceInstanceProperty = require("@babel/runtime-corejs3/core-js-stable/instance/slice");

var _Array$from2 = require("@babel/runtime-corejs3/core-js-stable/array/from");

var _Symbol = require("@babel/runtime-corejs3/core-js-stable/symbol");

var _getIteratorMethod = require("@babel/runtime-corejs3/core-js/get-iterator-method");

var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");

var _includes = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/includes"));

var _set = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/set"));

var _map = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/map"));

var _from = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/array/from"));

var _concat = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/concat"));

function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof _Symbol !== "undefined" && _getIteratorMethod(o) || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }

function _unsupportedIterableToArray(o, minLen) { var _context4; if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = _sliceInstanceProperty(_context4 = Object.prototype.toString.call(o)).call(_context4, 8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return _Array$from2(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

/**
 * 校验字符串：中文、英文、数字、特殊符号的组合
 *
 * @since 1.1.0
 * @category 正则
 * @param {string|number} str 需要校验的字符串.
 * @param {object} config 配置参数.
 * @param {boolean} config.isDetail 是否返回详细信息, 为true时返回CheckResult, false时返回boolean 默认: false.
 * @param {Array} config.combination 基础符号的组合，'cn'-中文，'en'-英文，'num'-数字，'symbol'-特殊符号（除汉字、英文字母、数字外所有其他符号），默认：[], 汉字、英文字母、数字、特殊符号都包含.
 * @param {String} config.includes 需额外包含的字符串, 默认为空
 * @param {String} config.excludes 需要剔除的字符串, 默认为空
 *
 * @returns { boolean|CheckResult } 校验结果 或 结果对象.
 *
 * @typedef {object} CheckResult
 * @property {boolean} status 校验结果
 * @property {string} errorMsg 错误提示
 * @property {RexExp} reg 校验数据使用的RexExp对象
 *
 * @example
 *
 * z.isBasicSymbol('中文abc', { combination: ['cn', 'en'] })
 * // => true
 * z.isBasicSymbol('abc123_', { combination: ['en', 'num'], includes: '_' })
 * // => true
 * z.isBasicSymbol('abc?', { combination: ['en', 'symbol'], excludes: '?><' })
 * // => false
 * z.isBasicSymbol('中文abc123', { isDetail: true, combination: ['en', 'num'] })
 * // { status: false, errorMsg: '格式错误!', reg: /^(([a-zA-Z]|[0-9]))+$/ }
 *
 */
function isBasicSymbol(str) {
  var _context3;

  var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
      _ref$isDetail = _ref.isDetail,
      isDetail = _ref$isDetail === void 0 ? false : _ref$isDetail,
      _ref$combination = _ref.combination,
      combination = _ref$combination === void 0 ? [] : _ref$combination,
      _ref$includes = (0, _includes.default)(_ref),
      includes = _ref$includes === void 0 ? '' : _ref$includes,
      _ref$excludes = _ref.excludes,
      excludes = _ref$excludes === void 0 ? '' : _ref$excludes;

  var rt = {
    status: false,
    errorMsg: ''
  };
  if (typeof str === 'number') str = "".concat(str);

  if (typeof str !== 'string') {
    throw new Error('str类型错误');
  }

  if (!Array.isArray(combination)) {
    throw new Error('combination类型错误');
  }

  if (typeof includes !== 'string') {
    throw new Error('includes类型错误');
  }

  if (typeof excludes !== 'string') {
    throw new Error('excludes类型错误');
  } // 校验includes和excludes是否有相同的字符


  var includesSet = new _set.default(includes);
  var excludesSet = new _set.default(excludes);
  var isOverlap = false;

  var _iterator = _createForOfIteratorHelper(includesSet),
      _step;

  try {
    for (_iterator.s(); !(_step = _iterator.n()).done;) {
      var char = _step.value;

      // 如果在第二个集合中也找到了这个字符，那么返回true
      if (excludesSet.has(char)) {
        isOverlap = true;
      }
    }
  } catch (err) {
    _iterator.e(err);
  } finally {
    _iterator.f();
  }

  if (isOverlap) {
    throw new Error('includes和excludes中不能有相同的字符');
  } // 定义基本正则表达式片段


  var patterns = {
    cn: /[\u4e00-\u9fa5]/,
    // 中文
    en: /[a-zA-Z]/,
    // 英文
    num: /[0-9]/,
    // 数字
    symbol: /[^\u4e00-\u9fa5a-zA-Z0-9]/ // 其他符号

  };
  var regexParts = '';

  if (combination.length === 0) {
    regexParts = [/[\s\S]/.source];
  } else {
    // 验证传入的类别并构建正则表达式字符串
    regexParts = (0, _map.default)(combination).call(combination, function (category) {
      if (patterns.hasOwnProperty(category)) {
        return patterns[category].source; // 获取基本正则表达式片段
      }

      throw new Error("\u4E0D\u652F\u6301\u7684combination: ".concat(category));
    });
  } // 处理includes参数


  if (includes) {
    var _context;

    // 如果includes是一个字符串，将其转换为字符集
    var includesRegex = (0, _map.default)(_context = (0, _from.default)(includes)).call(_context, function (char) {
      return char.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    }).join('');

    if (includesRegex) {
      // 添加includes字符集到正则表达式片段中
      regexParts.push("[".concat(includesRegex, "]"));
    }
  } // 构建排除字符的正则表达式片段


  var excludesRegex = '';

  if (excludes) {
    var _context2;

    // 使用一个负向前瞻断言来排除excludes中的字符
    excludesRegex = (0, _map.default)(_context2 = excludes.split('')).call(_context2, function (char) {
      var charRegex = char.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
      return "(?!".concat(charRegex, ")");
    }).join('');
  } // 组合所有正则表达式片段


  var regexStr = (0, _concat.default)(_context3 = "^(".concat(excludesRegex, "(")).call(_context3, regexParts.join('|'), "))+$"); // 先匹配指定的字符，然后可以匹配任意个排除的字符

  rt.reg = new RegExp(regexStr);

  if (rt.reg && !rt.reg.test(str)) {
    rt.errorMsg = '格式错误!';
  } else {
    rt.status = true;
  }

  return isDetail ? rt : rt.status;
}

module.exports = isBasicSymbol;